package com.example.pdf.util;

import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.font.constants.StandardFonts;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.utils.PdfMerger;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;

import java.io.IOException;
import java.util.List;

import cn.hutool.core.util.StrUtil;

/**
 * @author mrcode
 * @date 2022/1/21 20:27
 */
public class PDFUtil {
    /**
     * 合并多个 PDF 文件为一个
     *
     * @param list   要合并的 PDF 文件绝对路径列表
     * @param toFile 合并后的 PDF 文件绝对路径
     * @throws IOException
     */
    public static void merge(List<String> list, String toFile) throws IOException {
        final PdfDocument toPdf = new PdfDocument(new PdfWriter(toFile));
        PdfMerger merger = new PdfMerger(toPdf);
        for (String file : list) {
            final PdfDocument pdfDocument = new PdfDocument(new PdfReader(file));
            merger.merge(pdfDocument, 1, pdfDocument.getNumberOfPages());
            pdfDocument.close();
        }
        merger.close();
        toPdf.close();
    }

    /**
     * 添加页码； 在右下角添加
     *
     * @param fontSize 文字大小，一般为 15 比较合适
     * @param srcPath  原始 PDF 文件绝对路径
     * @param destPath 添加完水印后的 PDF 存放路径
     */
    public static void addPageNumber(int fontSize, String srcPath, String destPath) throws IOException {
        PdfDocument pdfDoc = new PdfDocument(new PdfReader(srcPath), new PdfWriter(destPath));
        Document doc = new Document(pdfDoc);
        PdfFont font = getPdfFont(null);
        // 文字高度则是字体大小
        final float textHeight = fontSize;
        final int numberOfPages = pdfDoc.getNumberOfPages();
        for (int i = 1; i <= numberOfPages; i++) {
            PdfPage pdfPage = pdfDoc.getPage(i);
            // 获取页面大小，考虑页面旋转
            Rectangle pageSize = pdfPage.getPageSizeWithRotation();
            // 当页面有旋转时，内容自动旋转
            pdfPage.setIgnorePageRotationForContent(true);

            // 构建页码
            final String text = StrUtil.format("{}/{}", i, numberOfPages);
            Paragraph paragraph = new Paragraph(text)
                    .setFont(font)
                    .setFontSize(fontSize);
            // 获取文字宽度
            final float textWidth = font.getWidth(text, fontSize);
            // 计算添加的位置坐标
            // 定位到水平垂直居中
            // float x = (pageSize.getLeft() + pageSize.getRight()) / 2;
            // 定位到右侧：根据文字宽度减少宽度，能动态的根据文字宽度调整，让文字不会超出屏幕外面
            float x = pageSize.getRight() - textWidth;
            // bottom 是 0，+ 20 就是底部往上 20
            // 定位到底部：根据文字高度动态往上调整，不会超出屏幕外面；
            float y = pageSize.getBottom() + textHeight + 10;

            // 参数分别为：文本、x 坐标、y 坐标、添加到底几页、文本水平对齐方式、文本垂直对齐方式、旋转弧度
            doc.showTextAligned(paragraph,
                    x, // 文本所在 x y 坐标，文字将围绕这个点进行对齐或则旋转
                    y,
                    i, // 添加到 PDF 第几页
                    TextAlignment.CENTER,   // 文本水平对齐方式
                    VerticalAlignment.TOP, // 文本垂直对齐方式
                    // 将 角度 转换为 弧度
                    (float) Math.toRadians(0));
        }
        doc.close();
    }

    /**
     * 获取字体，支持 afm、pfm、ttf、otf、woff、woff2 字体，ttc 目前直接报错
     *
     * @param fontPath 字体文件绝对路径，如果为空则返回默认的英文字体
     * @return
     */
    private static PdfFont getPdfFont(String fontPath) throws IOException {
        if (fontPath == null) {
            return PdfFontFactory.createFont(StandardFonts.HELVETICA);
        }
        return PdfFontFactory.createFont(
                fontPath,
                // 水平书写
                PdfEncodings.IDENTITY_H,
                // 是否将字体嵌入到目标文档中: 如果可能，嵌入字体
                PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED);
    }
}

